Intro to Svelte transitions
Posted on 2023-06-25 by
henrikvilhelmberglundSome quick info:
- There's fade, blur, fly, slide, scale. All of these are imported from svelte/transition.
- To use them add for example
transition:fly
, then arguments if neededtransition:fly={{x: 100}}
- You can also use
in:fade
orout:fade
if you only want a transition when an element is created or destroyed. Or if you want different transitions for in and out. - There are easings in svelte/easings if you want a smoother animation. For example
sineOut
Let's look at Li Hau Tan's example:
Here we have a TODO app without transitions. Let's try adding some transitions and see if it feels better to use.
Hall
<script>
import { browser } from "$app/environment";
const data = [
{ title: "Hall", items: ["Sweep the floor", "Mop the floor", "Throw the rubbish"] },
{ title: "Kitchen", items: ["Wash the plates", "Tidy the table", "Boil the soup"] },
{ title: "Toilet", items: ["Brush the sink", "Flush the toilet", "Scrub the floors"] },
];
let lists = [
{ show: true, items: [0, 1] },
{ show: false, items: [0] },
{ show: false, items: [0, 1] },
];
let media;
let noAnimation;
if (browser) {
media = matchMedia("(prefers-reduced-motion: reduce)");
noAnimation = media.matches;
media.onchange = (event) => {
noAnimation = event.matches;
};
}
function t() {
return {
delay: 0,
};
}
</script>
<div class="containery">
{#each lists as list, i (i)}
{#if list.show}
<div
on:introend={() => {
list.shown = true;
}}
on:outroend={() => {
list.shown = false;
}}
class="list">
<div class="title">{data[i].title}</div>
<button class="close" on:click={() => (list.show = false)}>X</button>
<ul class="items">
{#each list.items as item, index (item)}
<li class="item">
<button
on:click={() => {
list.items = list.items.filter((i) => i !== item);
}}><span>{data[i].items[item]}</span><span class="pl-4">X</span></button>
</li>
{/each}
{#if list.items.length !== 3}
<button
class="add-item"
on:click={() => {
const potential = new Set([0, 1, 2]);
list.items.forEach((item) => potential.delete(item));
list.items.push(Array.from(potential)[0]);
list.items = list.items;
}}>
Add item
</button>
{/if}
</ul>
</div>
{:else}
<button class="add-list" on:click={() => (list.show = true)}>+</button>
{/if}
{/each}
</div>
<style>
.containery {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
.list,
.add-list {
margin: 20px;
border: 1px solid #999;
border-radius: 4px;
padding: 20px;
box-shadow: 4px 4px 4px #ddd;
position: relative;
}
.title {
font-size: 18px;
font-weight: bold;
}
.close {
position: absolute;
top: 10px;
right: 10px;
background: none;
border: none;
cursor: pointer;
}
.items {
list-style: none;
padding: 0;
height: 250px;
}
.items li {
margin-bottom: 16px;
padding: 8px;
border: 1px solid #999;
border-radius: 4px;
box-shadow: 2px 2px 2px #ddd;
transition: all 0.5s ease;
}
.items li:hover {
box-shadow: 4px 4px 4px #ddd;
}
.item {
display: flex;
}
.item span:first-child {
flex: 1;
}
.add-list {
display: grid;
place-items: center;
font-size: 100px;
cursor: pointer;
background: rgba(0, 0, 255, 0.05);
color: blue;
border: none;
box-shadow: none;
}
.items li.add-item {
border: none;
background: none;
box-shadow: none;
color: blue;
text-align: center;
background: rgba(0, 0, 255, 0.05);
}
</style>